home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
scratch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
18KB
|
725 lines
/*
* $Id: scratch.c,v 0.91 1994/02/20 00:52:51 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* A. Scratch files for possible backing store. Neither portable nor
* efficient. Probably should make it portable.
*
* B. Hacks to read compressed and not-directly-supported formats
*
*/
#if !defined(lint) && defined(F_ID)
char *id_sh = "$Id: scratch.c,v 0.91 1994/02/20 00:52:51 zhao Pre-Release $";
#endif
#include "bit.h"
#include "dmalloc.h"
/******************************************************************
* Handle TMP file formats
*
* For the specification of the BIT1.0 format, See files in ../docs
* directory.
**************************************************************{*/
/************************* Limits and defines ********************/
#define TMPSIG "BIT1.0" /* signature */
#define TMPSIGL (sizeof(TMPSIG)-1) /* its length */
/*********************** Local variables ************************/
static int pc_resolution, channel, compression;
/**************************************************************/
int
TMP_desc(IPTR im)
{
char buf[10];
FILE *fp = im->fp;
fread(buf, 1, TMPSIGL, fp); /* ignore signature */
im->w = get2LSBF(fp);
im->h = get2LSBF(fp);
pc_resolution = getc(fp);
channel = getc(fp);
compression = getc(fp);
M_info("TMP_desc", "%s: Res=%d Channel=%d Comp=%d",
pc_resolution, channel, compression);
if (pc_resolution < 0 || pc_resolution > 2)
{
Bark("TMP_desc", "Bad PC resolution: %d", pc_resolution);
return -1;
}
if (channel < 0)
{
Bark("TMP_desc", "Bad color components: %d", channel);
return -1;
}
if (channel > 4 && !(channel == 5 && pc_resolution == 1))
{
Bark("TMP_desc", "Bad color components: %d", channel);
return -1;
}
if (channel == 0 || channel == 2)
{ /* colormap */
int ncolors = get2LSBF(fp);
if (ncolors < 0)
{
Bark("TMP_desc", "Bad colormap entries: %d", ncolors);
return -1;
}
im->colors = im->cmap->colors = ncolors;
if (pc_resolution == sizeof(pc_t))
{
fread(im->cmap->ct[0], sizeof(pc_t), ncolors, fp);
fread(im->cmap->ct[1], sizeof(pc_t), ncolors, fp);
fread(im->cmap->ct[2], sizeof(pc_t), ncolors, fp);
}
else
{ /* to be implemented */
Bark("TMP_desc", "highier resolution not supported yet");
return -1;
}
im->type = channel ? T_GMAP : T_CMAP;
}
else
{ /* truecolor */
im->type = channel == 1 ? T_GRAY : T_RGBA;
}
return 0;
}
/*****************************************************************/
int
TMP_load(IPTR im)
{
FILE *fp = im->fp;
size_t total = im->w * im->h;
long ok = total;
show_busy("Loading ...");
im->xi = get2LSBF(fp);
im->yi = get2LSBF(fp);
im->xf = im->xi + im->w - 1;
im->yf = im->yi + im->h - 1;
if (compression)
{
to_be_written("TMP_load compression");
return -1;
}
if (IS_CI(im))
{ /* colormap */
ok = fread(im->raster, im->esize, total, fp);
}
else if (channel != 5)
{ /* non-packed */
int r, g, b, a;
rgba_t *ras = im->raster, *rs;
/* if we get here, we know resolution must be 1 */
#if 0 /* forcing use getc */
int (*readit) (FILE *);
readit = (resolution == 1) ? fgetc : get2LSBF;
#else
#define readit getc
#endif
if (channel == 1)
{
for (rs = ras + total; ras < rs; ras++)
{
r = readit(fp);
*ras = Pack(r, r, r);
}
}
else if (channel == 3)
{
for (rs = ras + total; ras < rs; ras++)
{
r = readit(fp);
g = readit(fp);
b = readit(fp);
*ras = Pack(r, g, b);
}
}
else if (channel == 4)
{
for (rs = ras + total; ras < rs; ras++)
{
r = readit(fp);
g = readit(fp);
b = readit(fp);
a = readit(fp);
*ras = Pack4(r, g, b, a);
}
}
}
else
{ /* packed already */
ok = fread(im->raster, sizeof(rgba_t), total, fp);
}
end_busy();
return (ok > total / 2) ? im->h : -1;
}
/***************** Writing Routines *****************************/
static int packedpix = 1;
/* ARGSUSED */
const char *
TMP_wdefault(const IPTR im)
{
return packedpix ? "Packed" : "Non-packed";
}
/* ARGSUSED */
int
TMPdump_init(IPTR im)
{
return (packedpix = !packedpix);
}
int
TMP_dump(IPTR im)
{
size_t total = im->w * im->h;
FILE *fp = im->fp;
show_busy("Writing ...");
if (Badfwrite(TMPSIG, 1, TMPSIGL, fp))
return -1;
put2LSBF(im->w, fp);
put2LSBF(im->h, fp);
putc(sizeof(pc_t), fp);
/* always write channel 5 */
channel = IS_CI(im) ? (IS_GRAY(im) ? 2 : 0) :
(IS_GRAY(im) ? 1 : (packedpix ? 5 : 3));
putc(channel, fp);
putc(0, fp); /* compression */
if (IS_CI(im))
{
int ncolors = im->cmap->colors;
put2LSBF(ncolors, fp);
fwrite(im->cmap->ct[0], 1, ncolors, fp);
fwrite(im->cmap->ct[1], 1, ncolors, fp);
fwrite(im->cmap->ct[2], 1, ncolors, fp);
}
put2LSBF(im->xi, fp);
put2LSBF(im->yi, fp);
if (IS_CI(im))
{
fwrite(im->raster, sizeof(ci_t), im->w * im->h, fp);
}
else if (channel == 1)
{ /* grayscale */
register rgba_t *ras = im->raster, *rs;
for (rs = ras + total; ras < rs; ras++)
{
putc((*ras & 0xff), fp);
}
}
else if (channel == 3)
{ /* seperate RGB */
register rgba_t *ras = im->raster, *rs;
register int r, g, b;
for (rs = ras + total; ras < rs; ras++)
{
Unpack(*ras, r, g, b);
putc(r, fp);
putc(g, fp);
putc(b, fp);
}
}
else
{
fwrite(im->raster, sizeof(rgba_t), total, fp);
}
end_busy();
return fflush(fp);
}
/***********************************************************************
* END OF TMP FILE
******************************************************************}*/
/**************************************************************************
*
* FORMATS that rely on external program to convert to one of the known
* formats. Can't use popen(.....) because we need to guarantee seek-ability
*
**************************************************************************/
#include <stdlib.h> /* for system */
static const char *pref = ".BIT"; /* tmp file prefix */
extern IMG_IO img_io[];
/********************************************************************
* the driver routine that uncompress/converts or whatever to read
* an images description. It takes command names, options and whole
* bunch of things to do the magic
********************************************************************/
static int
fake_desc(IPTR im, const char *cmds[], const char *func, const char *prgs)
{
char cmd[1024];
const char *const *q = cmds;
int found[5], i, status, total;
char *tmp_file;
IMG_IO *p;
FILE *fp;
/* get a tmp file to hold the output */
if (!(tmp_file = get_tmpf(pref)))
{
Bark(func, "Unable to get tmpfile");
return -1;
}
update_filename(im->ifile);
update_format_info(im);
/* now try all given conversion commands. */
show_busy(prgs);
do
{
sprintf(cmd, *q, im->ifile, tmp_file);
status = system(cmd);
}
while (status && *++q);
end_busy();
if (status) /* did not succeed */
{
Bark(func, "Bad command");
del_tmpf(tmp_file);
return -1;
}
/*
* conversion is successful. Try to read it. Can't simply use open_image
* to do it because of bad recursion would occur
*/
if (!(fp = fopen(tmp_file, "r")))
{
del_tmpf(tmp_file);
return -1;
}
/* see if processed file is one of the formats we can handle */
if ((total = check_signature(fp, found, tmp_file)) <= 0)
{
del_tmpf(tmp_file);
return -1;
}
/*
* so far so good. Do all signature matches until we get a good
* description. However, before we hand over the stuff to get_desc, need
* to change the filename to the real file because canned library might
* ignore im->fp and want to open file and do its things ...
*/
strcpy(cmd, im->ifile);
strcpy(im->ifile, tmp_file);
im->fp = fp;
i = 0;
do
{
rewind(im->fp);
im->io = (p = img_io + found[i]);
im->t2b = p->t2b;
im->type = p->type;
if (!im->io->display)
im->io->display = Generic_display;
status = im->io->desc(im);
}
while (++i < total && status < 0);
/* now we can safely delete the file regardless status */
del_tmpf(tmp_file);
strcpy(im->ifile, cmd);
update_filename(im->ifile);
return status;
}
/**********************************************************************
* The writing routine. All depends on structure FakeDump. The format
* string should be a command name, and four string producers to accept
* option, infile, outfile and option2, e.g., "pnmtotiff %s %s > %s %s" is
* an acceptable one.
**********************************************************************/
typedef struct
{
const char *cmd; /* shell command to do it */
char *keys[4]; /* formats cmd accepts */
int optlast; /* for totiff. Weird stuff */
}
FakeDump;
/**********************************************************
* The driver
*********************************************************/
static int
fake_dump(IPTR im, FakeDump * fake, const char *opt1, const char *opt2,
const char *func, const char *prgs)
{
int in, err;
FakeDump *f = fake;
char cmd[MAXDLEN + MAXFLEN], sf[MAXDLEN + MAXFLEN];
char *tmpf;
const char *o1 = opt1 ? opt1 : "", *o2 = opt2 ? opt2 : "";
if (!(tmpf = get_tmpf(pref)))
{
Bark(func, "Unable to get tmpfile");
return -1;
}
/*
* again, need to save filenames. Some formats do its own things with
* file names ....
*/
strcpy(sf, im->ofile);
strcpy(im->ofile, tmpf);
do
{
/*
* if the writing routine takes multiple formats, always choose the
* format that is closest to current image
*/
err = (in = best_format(im, f->keys)) < 0;
/*
* if the format needed and the best format is not the same,
* convert to needed
*/
err = err || (img_io[in].type != T_FLEX &&
img_io[in].type != im->type &&
img_convert_type(im, img_io[in].type));
/* write current image to disk in proper format */
err = err || !(im->fp = fopen(tmpf, "w"));
err = err || (img_io[in].dump(im) < 0);
close_image(im);
/* generate the necassary shell command to do the job */
if (f->optlast)
sprintf(cmd, f->cmd, "", tmpf, sf, o2);
else
sprintf(cmd, f->cmd, o1, tmpf, sf, "");
/* do it */
M_info("Executing", cmd);
show_busy(prgs);
err = err || system(cmd);
}
while (++f && f->cmd && err);
del_tmpf(tmpf);
strcpy(im->ofile, sf);
end_busy();
return err;
}
/****************************************************************
* Compressed file hack. No much to do
****************************************************************/
#ifndef NO_COMPRESS
int
Compress_desc(IPTR im)
{
static const char *cmds[] =
{
"zcat %s > %s", 0
};
int status;
static char newinfo[128];
strcpy(newinfo, im->io->info);
status = fake_desc(im, cmds, "CompressDesc", "Uncompressing ...");
strcat(newinfo, im->io->key);
im->info = newinfo;
return status;
}
/***************************************************************
* after description, flow should've been directed to the true
* format reader via io->load, should not be here. If it reaches,
* something is very wrong
**************************************************************/
/* ARGSUSED */
int
Compress_load(IPTR im)
{
Bark("CompressLoad", "Should be be here");
return -1;
}
#endif /* !NO_COMPRESS */
/****************************************************************
* TIFF file support hack. Someday, I will make tiff a first
* class citizen.
*****************************************************************/
#ifndef NO_TIFF
/************************************************************
* The description routine. Again, no much to do, just call
* call fake_desc and done with it
***********************************************************/
int
TIFF_desc(IPTR im)
{
static const char *cmds[] =
{
"fromtiff %s %s",
"tifftopnm %s > %s",
0
};
int status;
const char *oldkey = im->io->key, *oldinfo = im->io->info;
/*
* must save old io->key and io->info because fake_desc will replace this
* with whatever it read, e.g., IRIS RGB, we certainly don't want to
* reading a tiff file while reporting we have read an IRIS RGB
*/
status = fake_desc(im, cmds, "TIFF_Desc", "Reading ...");
/* cheat again to get the reporting right. Two wrongs make a right! */
im->key = oldkey;
im->info = oldinfo;
return status;
}
/***************************************************************
* After description, flow should've been directed to the
* true loader via io->load. Should not be here
***************************************************************/
/* ARGSUSED */
int
TIFF_load(IPTR im)
{
Bark("TIFF_Load", "Should be be here");
return -1;
}
static int tifflzw;
/* ARGSUSED */
int
TIFF_dumpinit(IPTR im)
{
tifflzw = !tifflzw;
return 0;
}
/* ARGSUSED */
const char *
TIFF_wdefault(const IPTR im)
{
return tifflzw ? "Compress" : "No Compress";
}
/*********************************************************
* write a tiff file either thru totiff or pnmtotiff
*********************************************************/
int
TIFF_dump(IPTR im)
{
static FakeDump tiffdump[] =
{
/* totiff routiens */
{"totiff %s %s %s %s", /* command line */
{"iris", 0}, /* accepted formtats */
1 /* if option goes last (wierd) */
},
/* PBMPlus routines */
{"pnmtotiff %s %s > %s %s",
{"ppm", "pgm", "pbm", 0},
0
},
/* sentinel */
{0}
};
return fake_dump(im, tiffdump, tifflzw ? "-lzw" : "-none",
tifflzw ? "-c" : 0, "TIFFDump", "PleaseWait ...");
}
#endif /* ! NO_TIFF */
/** routines for developing bit *********/
#ifdef DEVELOP_BIT
/***************************************************************
* Generate a GL cursor bitmap (16x16 mono only)
***************************************************************/
int
CUR_dump(IPTR im)
{
unsigned short ch[17];
unsigned short *cur = ch;
bw_t *bw;
char vname[512], *t;
FILE *fp = im->fp;
int i, j, k;
if (im->w != 16 || im->h != 16)
{
Bark("GLCurDef", "Bad bitmap");
return -1;
}
strcpy(vname, im->ofile);
/* zap the extension if any */
if ((t = strchr(vname, '.')))
*t = '\0';
for (i = 0; i < im->h; i++)
{
bw = ((bw_t **) im->mraster)[i];
for (*cur = 0, j = 0, k = 15; j < 16; j++, k--, bw++)
*cur |= (*bw != 0) << k;
cur++;
}
/** write it */
fprintf(fp, "static unsigned short %s[] =\n {", vname); /* } VI */
for (cur = ch, i = 0; i < 16; i += 8)
{
fprintf(fp, "%c\n 0x%04x, ", i == 0 ? ' ' : ',', *cur++);
fprintf(fp, "0x%04x, ", *cur++);
fprintf(fp, "0x%04x, ", *cur++);
fprintf(fp, "0x%04x, ", *cur++);
fprintf(fp, "0x%04x, ", *cur++);
fprintf(fp, "0x%04x, ", *cur++);
fprintf(fp, "0x%04x, ", *cur++);
fprintf(fp, "0x%04x", *cur++);
} /* { *VI */
fputs("\n };\n", fp);
return fflush(fp);
}
int
CUR_desc(IPTR im)
{
return -1;
}
/*******************************************************************
* Write GL Patterns from a bitmap. Pattern is 32x32 bits packed
* into 2 * 32 shorts
*******************************************************************/
int
PAT_dump(IPTR im)
{
unsigned short ph[65], *pat;
bw_t *bw;
FILE *fp = im->fp;
int i, j, k;
char vname[512], *t;
if (im->w != 32 || im->h != 32)
{
Bark("GLPatternWrite", "Bad input bitmap");
return -1;
}
strcpy(vname, im->ofile);
/* zap the extension if any */
if ((t = strchr(vname, '.')))
*t = '\0';
pat = ph;
/* covert to GL patterns */
for (j = 0; j < im->h; j++)
{
bw = ((bw_t **) im->mraster)[j];
for (*pat = 0, k = 15, i = 0; i < 16; k--, i++, bw++)
*pat |= (*bw != 0) << k;
pat++;
for (*pat = 0, k = 15, i = 0; i < 16; k--, i++, bw++)
*pat |= (*bw != 0) << k;
pat++;
}
/** write it */
fprintf(fp, "static unsigned short %s[] =\n {", vname); /* } VI */
for (pat = ph, i = 0; i < 64; i += 8)
{
fprintf(fp, "%c\n 0x%04x, ", i == 0 ? ' ' : ',', *pat++);
fprintf(fp, "0x%04x, ", *pat++);
fprintf(fp, "0x%04x, ", *pat++);
fprintf(fp, "0x%04x, ", *pat++);
fprintf(fp, "0x%04x, ", *pat++);
fprintf(fp, "0x%04x, ", *pat++);
fprintf(fp, "0x%04x, ", *pat++);
fprintf(fp, "0x%04x", *pat++);
} /* { *VI */
fputs("\n };\n", fp);
return fflush(fp);
}
int
PAT_desc(IPTR im)
{
return -1;
}
#endif /* DEVELOP */